# -*-Perl-*-
package GenomeFiles::Processor;
use Bio::Root::Root;
use base qw(Bio::Root::Root);

our $VERSION = 0.01;
our %Defaults = ('gff_version' => 3,
		 'type'        => 'ncbi_genbank',
		 'rawfile_prefix' => 'raw',
    );
		 

=head2 new

 Title   : new
 Usage   : my $processor = GenomeFiles::Processor->new
                (-type => 'ncbi_genbank',
                 -directory  => '/project/genome_files/fungi/aspergillus',
                 -all_in_one  => 0,
                );
 Function:
 Returns : 
 Args    :


=cut

sub new {
  my($class,@args) = @_;

  if( $class =~ /GenomeFiles::Processor::(\S+)/ ) {
    my ($self) = $class->SUPER::new(@args);     
    $self->_initialize(@args);
    return $self;
  } else { 
    my %param = @args;
    @param{ map { lc $_ } keys %param } = values %param; # lowercase keys
    my $type = $param{'-type'} || $Defaults{'type'};

    # normalize capitalization to lower case
    $format = "\L$format";
    
    return unless( $class->_load_format_module($format) );
    return "GenomeFiles::Processor::${format}"->new(@args);
  }
}

sub _initialize {
    my ($self,@args) = @_;
    my ($dir,$allinone,$raw,
	$gff,$formatdir) = $self->_rearrange([qw(DIRECTORY ALL_IN_ONE
						   RAWFILE_PREFIX GFF_VERSION
						   FORMAT_DIR
						  )], @args);
    $self->directory($dir) if $dir;
    $self->all_in_one($allinone);
    $self->rawfile_prefix($raw || $Defaults{'rawfile_prefix'});
    $self->gff_version($gff || $Defaults{'gff_version'});
    $self->format_dir($formatdir) if $formatdir;

    return 1;
}

=head2 Getters and Setters

=head2 directory

 Title   : directory
 Usage   : $obj->directory($newval)
 Function: 
 Example : 
 Returns : value of directory (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub directory{
    my $self = shift;

    return $self->{'directory'} = shift if @_;
    return $self->{'directory'};
}



=head2 rawfile_prefix

 Title   : rawfile_prefix
 Usage   : $obj->rawfile_prefix($newval)
 Function: 
 Example : 
 Returns : value of rawfile_prefix (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub rawfile_prefix{
    my $self = shift;

    return $self->{'rawfile_prefix'} = shift if @_;
    return $self->{'rawfile_prefix'};
}

=head2 format_dir

 Title   : format_dir
 Usage   : $obj->format_dir($newval)
 Function: 
 Example : 
 Returns : value of format_dir (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub format_dir{
    my $self = shift;

    return $self->{'format_dir'} = shift if @_;
    return $self->{'format_dir'};
}


=head2 gff_version

 Title   : gff_version
 Usage   : $obj->gff_version($newval)
 Function: 
 Example : 
 Returns : value of gff_version (a scalar)
 Args    : on set, new value (a scalar or undef, optional)


=cut

sub gff_version{
    my $self = shift;

    return $self->{'gff_version'} = shift if @_;
    return $self->{'gff_version'};
}

=head2 Main routines

sub process {
    shift->throw("not implemented in the Base class");
}

sub write {
    shift->throw("not implemented in the Base class");

}


=head2 Utility functions

sub open_file {
    my ($filename) = shift;
    my $fh;
    if( $filename =~ /\.(gz|bz2|Z)/ ) {
	my $exe = $Uncompress{$1};
	open($fh, "$exe $filename |") || $self->throw("$exe $filename: $!");
    } else {
	open($fh "<$filename") || $self->throw("$filename: $!");
    }
    return $fh;
}

=head2 _load_format_module

 Title   : _load_format_module
 Usage   : *INTERNAL SearchIO stuff*
 Function: Loads up (like use) a module at run time on demand
 Example : 
 Returns : 
 Args    : 

=cut

sub _load_format_module {
  my ($self,$format) = @_;
  my $module = "Bio::PopGen::IO::" . $format;
  my $ok;
  
  eval {
      $ok = $self->_load_module($module);
  };
  if ( $@ ) {
      print STDERR <<END;
$self: $format cannot be found
Exception $@
For more information about the Bio::PopGen::IO system please see the 
Bio::PopGen::IO docs.  This includes ways of checking for formats at 
compile time, not run time
END
  ;
  }
  return $ok;
}



1;
